/** @file    WidgetWoshBrowser.cpp
 *  @author  Alessandro Polo
 *  @version $Id: WidgetWoshBrowser.cpp 2178 2010-03-19 11:02:55Z alex $
 *  @brief
 * File containing methods for the wosh::gui::WidgetWoshBrowser class.
 * The header for this class can be found in WidgetWoshBrowser.h, check that file
 * for class description.
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

 #include "WidgetWoshBrowser.h"
 #include "ui_WidgetWoshBrowser.h"

 #include <core/Request.h>
 #include <core/Response.h>
 #include <core/MethodsDef.h>
 #include <core/SecurityManager.h>
 #include <core/NetworkManager.h>
 #include <core/WoshKernel.h>


using namespace std;
namespace wosh {
 namespace gui {

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WidgetWoshBrowser::WidgetWoshBrowser(QWidget *parent) : QWidget(parent), IWidget()
 {
	this->m_ui = new Ui::WidgetWoshBrowser();
	this->m_ui->setupUi(this);

	this->getWidgetURI().setName( Utilities::format("WidgetWoshBrowser#%10lu", Utilities::randomLong()) );
	this->getTargetURI().clearPathName();

	this->setWindowTitle("WOSH Browser");

	this->treeModel = new WoshObjectTreeModel( new WoshObject(), this);
	connect(this->treeModel, SIGNAL(s_requestChildrenOf(WoshObject*)), this, SLOT(treeModel_requestChildrenOf(WoshObject*)));
	this->treeModel->setFetchMore( true );
	this->m_ui->treeView->setModel(this->treeModel);

	this->wTableModel = new WoshTableModel(NULL, this);
	this->m_ui->tableViewChildren->setModel(this->wTableModel);

	connect(this->m_ui->treeView, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(doubleClicked(const QModelIndex&)));
	connect(this->m_ui->treeView, SIGNAL(clicked(const QModelIndex&)), this, SLOT(clicked(const QModelIndex&)));

	connect(this->m_ui->btnRefresh, SIGNAL(clicked()), this, SLOT(refreshAll()));
	connect(this->m_ui->btnOptions, SIGNAL(clicked()), this, SLOT(btnOptions_clicked()));

	connect(this->m_ui->tBtnRefreshCurrent, SIGNAL(clicked()), this, SLOT(tBtnRefreshCurrent_clicked()));

	init();
}

WidgetWoshBrowser::~WidgetWoshBrowser()
{
	delete this->m_ui;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

void WidgetWoshBrowser::changeEvent(QEvent *e)
{
    QWidget::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        m_ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

void WidgetWoshBrowser::refreshAll()
 {
	requestHosts();

	if ( this->m_ui->chkAutoLoadKernelLocal->isChecked() ) {
		Request* request_local_children = new Request( _METHOD_List );
		Message* message = new Message(request_local_children);
		message->setDestination( URI::LocalKernel() );
		postMessageForTarget(message);
	 }
 }

void WidgetWoshBrowser::requestHosts() {
	Request* request_hosts = new Request( _NetworkManager_METHOD_Hosts_list );
	Message* message = new Message(request_hosts);
	message->getDestination().setKernelName(GuiCache::CurrentKernel);
	message->getDestination().setName("Network");
	postMessageForTarget(message);
 }


//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WoshObject* WidgetWoshBrowser::getSelectedItem()
 {
	QModelIndexList iList = this->m_ui->treeView->selectionModel()->selectedIndexes();
	if ( iList.empty() )
		return NULL;
	return static_cast<WoshObject*>(iList.at(0).internalPointer());
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

void WidgetWoshBrowser::refresh_inspector( const WoshObject* item, bool force_refresh )
 {
	this->m_ui->wWidgetProperties->reset();
	this->m_ui->wWidgetMethods->reset();

	if ( item == NULL ) {
		this->m_ui->lblCurrentObject->setText("");
		this->m_ui->lblItemName->setText("");
		this->m_ui->lblItemURI->setText("");
		this->m_ui->lblItemType->setText("");
		this->m_ui->listItemInterfaces->clear();
		this->m_ui->lblItemUpdated->setText("");
		if ( !force_refresh )
			return;

		return;
	 }

	this->m_ui->lblCurrentObject->setText( tr("Selected: %1 [%2]").arg(item->getRemoteName().c_str()).arg(item->getRemoteURI().toString().c_str()) );
	this->m_ui->lblItemName->setText( item->getRemoteName().c_str() );
	this->m_ui->lblItemURI->setText( item->getRemoteURI().toString().c_str() );
	this->m_ui->lblItemType->setText( item->getRemoteType().c_str() );
	this->m_ui->listItemInterfaces->clear();
	this->m_ui->listItemInterfaces->addItems( item->getInterfaces() );
	this->m_ui->lblItemUpdated->setText( tr("Updated @ %1").arg(Utilities::getTimeStampUTF(item->getUpdated()).c_str()) );

	this->m_ui->wWidgetProperties->setTargetURI( item->getRemoteURI() );
	this->m_ui->wWidgetMethods->setTargetURI( item->getRemoteURI() );

	if ( force_refresh || this->m_ui->tabWidget->currentIndex() == 1 )
		this->m_ui->wWidgetProperties->refreshAll();
	if ( force_refresh || this->m_ui->tabWidget->currentIndex() == 2 )
		this->m_ui->wWidgetMethods->refreshAll();
	if ( force_refresh || this->m_ui->tabWidget->currentIndex() == 3 )
		this->wTableModel->loadTable(NULL);

 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

void WidgetWoshBrowser::clicked( const QModelIndex & index )
 {
	WoshObject* item = static_cast<WoshObject*>(index.internalPointer());
	if ( item == NULL ) return;
	treeModel_requestChildrenOf(item);
	refresh_inspector(item, false);
 }

void WidgetWoshBrowser::doubleClicked( const QModelIndex & index )
 {
	WoshObject* item = static_cast<WoshObject*>(index.internalPointer());
	if ( item == NULL ) return;
	refresh_inspector(item, true);
	emit request_create_GUI(item->getRemoteName(),item->getRemoteType(), item->getRemoteURI(), QStringList() );
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

void WidgetWoshBrowser::btnOptions_clicked()
 {
	this->m_ui->stackedWidget->setCurrentIndex(this->m_ui->btnOptions->isChecked());
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

void WidgetWoshBrowser::tBtnRefreshCurrent_clicked()
 {
	WoshObject* item = getSelectedItem();
	if ( item == NULL ) return;
	treeModel_requestChildrenOf(item);
	refresh_inspector(item, true);
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

void WidgetWoshBrowser::treeModel_requestChildrenOf( WoshObject* item )
 {
	if ( item == NULL ) return;
	Request* request_children = new Request( _METHOD_List );
	Message* message = new Message(request_children);
	message->setDestination(item->getRemoteURI());
	postMessageForTarget(message);
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

void WidgetWoshBrowser::busMessage( const Message& message, const Bus* )
 {
	if ( message.isEmpty() ) return;

	// parse responses
	if ( message.getContent()->isResponse() ) {
		const wosh::Response* response = message.getContent()->asResponse();
		if ( !response->hasData() ) return;
		if ( !response->getData()->isClass(_Table_TYPE) ) return;
		const wosh::Table* table = dynamic_cast<const wosh::Table*>(response->getData());

		if ( response->getMethod() == _NetworkManager_METHOD_Hosts_list ) {
			WoshObject kernel;
			kernel.setRemoteType(_WoshKernel_TYPE);
			kernel.setParent(this->treeModel->getRootItem(), false);
			updateObjectsFromTable( table, this->treeModel->getRootItem(), &kernel );
			
			std::vector<WoshObject*>::const_iterator it;
			std::vector<WoshObject*>::const_iterator it_end = this->treeModel->getRootItem()->getChildren().end();
			for ( it=this->treeModel->getRootItem()->getChildren().begin(); it!=it_end; it++ ) {
				if ( *it == NULL ) continue;
				(*it)->getRemoteURI().clearPathName();
				(*it)->getRemoteURI().setKernelName( (*it)->getRemoteName() );
			 }
			this->treeModel->getRootItem()->setUpdated();
			this->treeModel->updated();
		 }
		else if ( response->getMethod() == _METHOD_List ) {
			this->treeModel->updateChildren( table, message.getSource() );
			WoshObject* cObj = getSelectedItem();
			if ( cObj != NULL && cObj->getRemoteURI() == message.getSource() )
				this->wTableModel->loadTable(table);
		 }
	}


 }


//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

 }; // namespace gui
}; // namespace wosh
